package Market;

import java.util.*;
import edu.iastate.jrelm.rl.SimpleStatelessLearner;
import sim.engine.*;


public class Market extends SimState{
	
	private static final long serialVersionUID = 6628525522939315274L;
												
												/** Priorities counter to fire agents in a chosen order */
	  private int count = 0;
												/** number of Branches*/
	  private int N;
	  											/** number of Nodes*/
	  private int K;
	  											/** Boolean used to separate GenCo's methods execution  */
	  boolean Switch;
	  											/** Number of days of market operation */
	  private int TotalDays = 10;
	  
	  
// GenCo												
												/** number of GenCos */
	  private int I;
	  											/** GenCos list */
	  private ArrayList GenCoList;
	  											/** Action domains list */
	  private ArrayList ADList;
	  											/** Learners list */
	  private ArrayList LearnerList;
	  											/** GenCo's Data: {Gen ID, at Node, FCost, aT, bT, CapTL, CapTU, Initial Money in pounds} */
	  private double[][] GenCoData;
	  											/** Learning Data: {initial propensity, Cooling, Recency, Experimentation, M1, M2, M3, RIMaxL, RIMaxU, RIMinC, SlopeStart, Reward Selection} */
	  private double[][] LearningData;
	  											/** True Supply Offer: {aT,bT,CapTL,CapTU} */
	  private double[][] TSupplyOffer;
	  											/** Reported Supply Offer: {aR,bR,CapRL,CapRU} */
	  private double[][] RSupplyOffer;
	  											/** Hourly power production quantity by GenCos */
	  private double[][] Commitment;
	  											/** GenCo's accumulative money holding, money (new) = money(previous) + dailyProfit(new) */
	  private double[] GenCoMoney;
	  
	  SimpleStatelessLearner Learner;
	  
// LSE
												/** number of LSEs */
	  private int J;      
	  											/** LSE's Data: {LSE ID, at Node, L(0), L(1),L(2),L(3),L(4), ...,L(23)} */
	  private double[][] LSEData;
	  											/** LSE's list */
	  private ArrayList LSEList;
	  											/** LSE's load profile for each hour [Hour][LSE] */
	  private double[][] LoadProfile;
	  											/** Twenty-four hours */
	  private static final int Hours = 24;

// ISO
	  											/** Local marginal price for each hour and node [Hour][Node] */
	  private double [][] LMP;

	  
//C-O-N-S-T-R-U-C-T-O-R------------------------------------------------------------------------------------------------------------------------------  
      public Market(long seed)
        {
        super(seed);
        }
//-------------------------------------------------------------------------------------------------
    

      public void start()
        {
        super.start();
        
        	Initials.InitGenCo  initG = new Initials.InitGenCo();
        	Initials.InitLSE    initL = new Initials.InitLSE();
        	Initials.InitBranch initB = new Initials.InitBranch();
        	Initials.InitNode initN = new Initials.InitNode();
        
        	I = initG.getNGenCo();  			// Obtains number of GenCos
        	J = initL.getNLSE();				// Obtains number of LSEs
        	N = initB.getNBranch();				// Obtains number of Branches
        	K = initN.getNNode();				// Obtains number of Nodes
        
        	ElGrid elgrid = new ElGrid();
        	GenCoMoney = new double[I];
        
//----GenCo------------------------------------------------             	       	
        for(int d=0; d<TotalDays; d++){  
			Switch		 = false;
			LearnerList  = new ArrayList();
        	ADList		 = new ArrayList();
        	GenCoList    = new ArrayList();
        	GenCoData    = new double[I][8];
        	LearningData = new double[I][12];
        	TSupplyOffer = new double[I][4];
        	RSupplyOffer = new double[I][4];

        	GenCoData    = initG.getGenCoData();    // Obtains GenCos' data
        	LearningData = initG.getLearningData(); // Obtains GenCos' learning data
        	
/* ********* Money update needs to be fixed***************************************
 	
        	        if (d>0){		
               		  for (int i=0;i<I;i++){               			
            		  GenCoData[i][7]= getGenCoMoney()[i];
            		  }	
        	        }
 ***************************************************************************/        	
       	  
        	for(int i=0; i<I; i++){
        		count++;
        		GenCo gen = new GenCo(GenCoData, LearningData, i, -890999481, this, d, Switch);  // Initiates a new GenCo      	
        		schedule.scheduleOnce(gen, count);        	   									 // Schedules this GenCo     	
        	
        		LearnerList.add(gen.getLearner());
        		
        		//elgrid.addGenCoAtNodeK(gen,(i+1));            
        		//GenCoList.add(gen);        		
        	}             	
//----- LSE-------------------------------------------------      
        	LSEList = new ArrayList();
        	LSEData = new double[J][26];
        	LoadProfile = new double[Hours][J] ;
        	
        	LSEData = initL.getLSEData();         				    // Obtains LSEs' data
        	
        	for (int h=0; h<Hours; h++){
        		for(int j=0; j<J; j++){ 
        			count++;    		
        			LSE lse = new LSE(LSEData, j, h, this);      	// Initiates a new LSE   	        		
        			schedule.scheduleOnce(lse, count);				// Schedules this LSE
       		    
        			//elgrid.addLSEAtNodeK(lse,(j+1));            
        			//LSEList.add(lse);                	
        		}
        	}
//----- ISO-------------------------------------------------     	
        	LMP = new double[Hours][K];
        	Commitment = new double[Hours][I];
        		
        	for (int h=0; h<Hours; h++){ 
        		count++;
        		ISO iso = new ISO(I, J, K, N, h, GenCoData, LSEData, this);					// Initiates a new ISO
        		schedule.scheduleOnce(iso, count);					// Schedules this ISO
        		}
           
//----- GenCo----------------------------------------------           
        	Switch = true;
        		        		 
	 		for(int i=0; i<I; i++){   
	 			count++;	 				
	 			System.out.println("Ushiol learnel" );
	 			GenCo gen = new GenCo(GenCoData, i, this, d, Switch, LearnerList);        	// Initiates a new GenCo 
	 			schedule.scheduleOnce(gen, count);      									// Schedules this GenCo 
	 		}
	 	}
     }

//-------M-A-I-N---------------------------------------------------------------------------------------
    public static void main(String[] args){
        Market market = new Market(System.currentTimeMillis());       
        market.start();
        long steps = 0;
        //while(steps < 5000)
        
        for(int i=0; i<1; i++){
        	market.schedule.step(market);
        	steps = market.schedule.getSteps();
        }
        
        System.out.println("Done!!!");
        market.finish();
        System.exit(0);
    }
    
//----- Set and Get methods------------------------------------------------------------------------   

    /** Adds LSEs to the list */   
    public void setLSEList(Object lselist){
    	LSEList.add(lselist);   	
    }
//-------------------------------------------------------------------------------------------------    
   
    /** Sets LSE's load profile for every hour and every LSE */ 
    public void setLoadProfile(double loadprofile, int h, int jj){
    	LoadProfile[h][jj] = loadprofile;
    } 
 //-------------------------------------------------------------------------------------------------    
    /** Returns hourly load profiles */   
    public double[][] getLoadProfile(){
    	return LoadProfile;
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Sets true supply offer for each GenCo */ 
    public void setTSupplyOffer(double[] tsupplyoffer, int g){
    	for (int i=0; i<4; i++){
    		TSupplyOffer[g][i] = tsupplyoffer[i]; 	
    	}
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Sets reported supply offer for each GenCo */
    public void setRSupplyOffer(double[] rsupplyoffer, int g){
    	for (int i=0; i<4; i++){
    		RSupplyOffer[g][i] = rsupplyoffer[i]; 	
    	}
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Returns reported supply offer */
    public double[][] getRSupplyOffer(){
    	return RSupplyOffer;
    }
    
//-------------------------------------------------------------------------------------------------    
   
    /** Returns true supply offer */
    public double[][] getTSupplyOffer(){
    	return TSupplyOffer;
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Adds action domains to the list */
    public void addAactionDomain(ArrayList adlist){    	
    	ADList.add(adlist);
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Sets Learner */
    public void setLearnerList(SimpleStatelessLearner learner){    	
    	LearnerList.add(learner);
    	System.out.println("Seted");
    }
//-------------------------------------------------------------------------------------------------    
   
    /** Adds GenCos to the list */
    public void addGenCo(Object genco){    	
    	GenCoList.add(genco);
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Returns GenCos' list */
    public ArrayList getGenCo(){    	
    	return GenCoList;
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Sets LMP list for each hour and node */
    public void setLMPList(double[] lmp, int h ){    	 	
    	for (int i=0; i<K; i++){
    		LMP[h][i] = lmp[i];
    	}
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Sets boolean Switch */
    public void setSwitch(boolean sw){    	
    	Switch = sw;
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Returns boolean Switch */
    public boolean getSwitch(){
    	return Switch;
    }
//-------------------------------------------------------------------------------------------------    
    /** Sets hourly power production quantity for each GenCo */
    public void setCommitment(double[] commitment, int h ){   	 
    	for (int i=0; i<I; i++){
    		Commitment[h][i] = commitment[i];
    	}
    }
//-------------------------------------------------------------------------------------------------    
    /** Returns hourly power production quantity by GenCos  */
    public double[][] getCommitment(){
    	return Commitment;	
    }
//-------------------------------------------------------------------------------------------------    
    
    /** Returns LMP */
    public double[][] getLMP(){
    	return LMP;	
    }
//-------------------------------------------------------------------------------------------------    
 
    /** Sets accumulative money holding for each GenCo*/
	public void setGenCoMoney(int i, double gencomoney){
		GenCoMoney[i] = GenCoMoney[i]+gencomoney;		
		//if (i==0){
		//System.out.println(GenCoMoney[i]);}
		//System.out.println("i= "+i+" "+GenCoMoney[i]+"   "+gencomoney[i]);
	}
//-------------------------------------------------------------------------------------------------    

	/** Returns GenCo's accumulative money holding*/
	public double[] getGenCoMoney(){		
		return GenCoMoney;
	}
//-------------------------------------------------------------------------------------------------    

}
